/*
 * Feeder.java
 *
 * Created on May 6, 2007, 2:01 PM
 *
 */

package sbc.fabrik.cli;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.xvsm.api.core.*;
import org.xvsm.client.ClientCapi;
import org.xvsm.ms.exceptions.TimeoutExpiredException;
import sbc.fabrik.model.Feature;
import sbc.fabrik.model.Platine;
import sbc.fabrik.model.Sensor;
public class Feeder {
    static String n;

    /** Creates a new instance of Feeder */
    public Feeder() {
    }
    
    public static void help() {
        System.out.println("\n*** FabrikShell Commands ***\n");
        System.out.println("\\s, sensor <id> <feature> [[<feature>] [<feature>]]: new sensor.");
        System.out.println("\\p, platine <id>: new platine.");
        System.out.println("\\r, read: read space.");
        System.out.println("\\q, quit: quit program.");
        System.out.println("\\h, help: this message.\n");
        System.out.println("****************************\n");
    }
    
    
    public static void main(String[] args) {
        try {
            Logger.getLogger("org.xvsm.client").setLevel(Level.FATAL);
            
            Capi capi;
            ContainerRef cref = null;
            
            
            
            if (args.length != 1) {
                 System.out.println("Usage: java -cp <classpath> sbc.fabrik.cli.Feeder http://localhost:8080/xvsm/xvsm\n using embeded core");
                // use embeded xvsm core
                capi = CapiFactory.createCapi();
                
            } else {
                // Get an instance of the capi and initialize it.
                // Capi capi = CapiFactory.createCapi();
                capi = new ClientCapi(args[0]);
            }
            capi.init(false);
            cref = capi.createContainer(CoordinationTypes.FIFO);
            
            /* starting cli shell */
            BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
            
            System.out.println("\nFabrikShell started at " + (new Date()).toString());
            System.out.println("Type '\\h' or 'help' for help.\n");
            boolean run = true;
            while(run) {
                
                System.out.println("\nFabrik\\> ");
                System.out.flush();
                String command = input.readLine().trim();
                //String command = input.readLine();
                //System.out.println("command\\> " + command);
                if(command.equalsIgnoreCase("quit") || command.equalsIgnoreCase("\\q")) {
                    System.out.println("\nGood Bye!\n");
                    //dirty...
                    //System.exit(0);
                    
                    run = false;
                    
                } else if(command.startsWith("help") || command.startsWith("\\h")) {
                    help();
                    continue;
                } else if(command.startsWith("sensor") || command.startsWith("\\s")) {
                    StringTokenizer paramTokenizer = new StringTokenizer(command, " ");
                    paramTokenizer.nextToken();
                    
                    int sid =  Integer.valueOf((String)paramTokenizer.nextToken()).intValue();
                    Sensor sensor = new Sensor(sid);
                    
                    while (paramTokenizer.hasMoreTokens()) {
                        String featureName = (String)paramTokenizer.nextToken();
                        try{
                            
                            sensor.addFeature(Feature.valueOf(featureName));
                            
                        } catch (IllegalArgumentException iae) {
                            System.out.println(featureName + ": unknown feature");
                            System.out.println("valid values are:");
                            for(Feature f: Feature.values()) {
                                System.out.println(f.name() + "\t(" + f.getLabel() + ")");
                            }
                        }
                    }
                    
                    
                    
                    Entry classEntry = Entry.Factory.newInstance(ValueTypes.STRING_UTF8, "SENSOR");
                    Entry idEntry = Entry.Factory.newInstance(ValueTypes.INTEGER, sensor.getSid());
                    
                    Tuple tuple = new Tuple();
                    tuple.addEntry(classEntry);
                    tuple.addEntry(idEntry);
                    
                    for (Feature f: sensor.getFeatures()) {
                        Entry featureEntry = Entry.Factory.newInstance(ValueTypes.STRING_UTF8, f.getLabel());
                        tuple.addEntry(featureEntry);
                    }
                    
                    List<Entry> entries = new LinkedList<Entry>();
                    entries.add(tuple);
                    
                    // Write the list of Entries into the created container.
                    capi.write(cref, entries);
                    
                    
                    System.out.println("Wrote:" + sensor);
                }
                
                else if(command.startsWith("platine") || command.startsWith("\\p")) {
                    StringTokenizer paramTokenizer = new StringTokenizer(command, " ");
                    paramTokenizer.nextToken();
                    if(!paramTokenizer.hasMoreTokens()) {
                        help();
                        continue;
                    }
                    
                    int pid =  Integer.valueOf((String)paramTokenizer.nextToken()).intValue();
                    
                    Platine p = new Platine(pid);
                    
                    Entry a0 = Entry.Factory.newInstance(ValueTypes.STRING_UTF8, "PLATINE");
                    Entry a1 = Entry.Factory.newInstance(ValueTypes.INTEGER, p.getPid());
                    Tuple t1 = new Tuple();
                    t1.addEntry(a0);
                    t1.addEntry(a1);
                    List<Entry> entries = new LinkedList<Entry>();
                    entries.add(t1);
                    
                    // Write the list of Entries into the created container.
                    capi.write(cref, entries);
                    
                    
                    System.out.println("Wrote:" + p);
                }
                
                else if(command.startsWith("read") || command.startsWith("\\r")) {
                    // Read and delete the elements from the space.
                    boolean empty = false;
                    while (!empty) {
                        try {
                            List<Entry> read = capi.take(cref,1);
                            // The first element in the list is the tuple.
                            Tuple t = (Tuple) read.get(0);
                            // Get the entries of the tuple
                            List<Entry> elements = t.getValue();
                            
                            for (Entry e: elements) {
                                System.out.print(e.getValue() + " ");
                            }
                            System.out.println();
                        } catch (TimeoutExpiredException tee) {
                            empty = true;
                            System.out.println("Space Empty!");
                        }
                    }
                }
                
            }
            capi.shutdown(true);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
